<?php

namespace App\Service\Product;

use App\Dao\Product\ProductDao;
use App\Dao\Product\StoreProductDao;
use App\Dao\User\UserDao;
use App\Model\Product\Product;
use App\Model\Product\StoreProduct;
use App\Model\Product\StoreProductAttr;
use App\Model\Product\StoreProductAttrResult;
use App\Model\Product\StoreProductAttrValue;
use App\Model\Product\StoreProductDescription;
use App\Service\BaseService;
use App\Service\Service;
use App\Tool\Collect;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Collection;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\Arr;

class ProductService extends BaseService
{

    /**
     * @Inject()
     * @var StoreProductDao
     */
    protected $storeProductDao;

    /**
     * @Inject()
     * @var UserDao
     */
    protected $userDao;

    public function list($params)
    {
        return $this->storeProductDao
            ->params($params)->getList();
    }

    public function mubiao(Collect $params)
    {
        $data = $this->storeProductDao
            ->params($params)->tap(function ($query) use ($params) {
                if ($params->offsetExists('sort_key') && $params->get('sort_key')) {
                    $sort_key = $params->get('sort_key');
                    $sort_direction = $params->get('sort_direction');
                    $query->orderBy($sort_key, $sort_direction);
                }
            })->getList();

        $userId = $params->get('user_id');
        $integral = $this->userDao->where('uid', $userId)->value('integral');
        $data->transform(function ($item) use ($integral) {
            dump($integral, $item->price);
            $item->rate = min(intval($integral / $item->price), 100);
            return $item;
        });

        return $data;
    }

    public function add(Collect $params)
    {
        $params->set('slider_image', function ($slider_image) {
            return json_encode(explode(',', $slider_image));
        });
        $params->set('image', json_decode($params->get('slider_image'), true)[0]);
        $params->set('cate_id', function ($cate_id) {
            return implode(',', $cate_id);
        });
        $attrData = _Collect(json_decode($params->get('attrData'), true));
        $attrs = _Collect(json_decode($params->get('attrs'), true));
        $params->offsetSet('stock', $attrData->sum(function ($item) {
            return $item['stock'];
        }));
        $params->offsetSet('price', $attrData->min(function ($item) {
            return $item['price'];
        }));
        $params->offsetSet('cost', $attrData->min(function ($item) {
            return $item['cost'];
        }));
        $params->offsetSet('ot_price', $attrData->min(function ($item) {
            return $item['ot_price'];
        }));
        $productData = $params->only(
            'unit_name',
            'stock',
            'cost',
            'price',
            'description',
            'image',
            'cate_id',
            'slider_image',
            'freight',
            'is_show',
            'is_virtual',
            'postage',
            'store_name',
            'spec_type'
        );

        Db::beginTransaction();
        try {
            $productObject = $this->storeProductDao->create($productData->toArray());
            $result = $this->getAttrResult((clone $attrs), $attrData);
            $productObject->StoreProductAttrResult()->save(new StoreProductAttrResult([
                'result' => json_encode($result)
            ]));

            $this->storeProductDescription
                ->updateOrCreate(['product_id' => $productObject->id], $params->only(['description'])->toArray());

            $attrData->transform(function ($attr) {
                return new StoreProductAttrValue($attr);
            });
            $attrs->transform(function ($attr) {
                return new StoreProductAttr([
                    'attr_name' => $attr['title'],
                    'attr_values' => implode(', ', json_decode($attr['values'], true)),
                ]);
            });
            $productObject->StoreProductAttrValue()->saveMany($attrData->all());
            $productObject->StoreProductAttr()->saveMany($attrs->all());
            Db::commit();
        } catch (\Exception $exception) {
            Db::rollBack();
            dd($exception->getMessage());
        }
        return $productObject;
    }

    /**
     * @Inject()
     * @var StoreProductDescription
     */
    public $storeProductDescription;

    public function edit($id, Collect $params)
    {
        $params->set('slider_image', function ($slider_image) {
            return json_encode(explode(',', $slider_image));
        });
        $params->set('image', json_decode($params->get('slider_image'), true)[0]);
        $params->set('cate_id', function ($cate_id) {
            return implode(',', $cate_id);
        });
        $attrData = _Collect(json_decode($params->get('attrData'), true));
        $attrs = _Collect(json_decode($params->get('attrs'), true));
        $params->offsetSet('stock', $attrData->sum(function ($item) {
            return $item['stock'];
        }));
        $params->offsetSet('price', $attrData->min(function ($item) {
            return $item['price'];
        }));
        $params->offsetSet('cost', $attrData->min(function ($item) {
            return $item['cost'];
        }));

        $params->offsetSet('ot_price', $attrData->min(function ($item) {
            return $item['ot_price'];
        }));

//        $productData = $params->only(
//            'unit_name',
//            'stock',
//            'cost',
//            'price',
//            'description',
//            'image',
//            'cate_id',
//            'slider_image',
//            'freight',
//            'is_show',
//            'is_virtual',
//            'postage',
//            'store_name',
//            'spec_type'
//        );
//        dd(json_decode($productData, true));
//        $slider_image = $params->get('slider_image');


        Db::beginTransaction();
        try {

            $productObject = $this->storeProductDao->where('id', $id)->firstOrError();
            $productObject->fill($params->toArray());

            $productObject->save();
            $this->storeProductDescription
                ->updateOrCreate(['product_id' => $productObject->id], $params->only(['description'])->toArray());

            $this->updateAttr($productObject, clone $attrs);
            $this->updateAttrResult($productObject, clone $attrs, $attrData);
            $this->updateAttrValue($productObject, $attrData);

            Db::commit();
        } catch (\Exception $exception) {
            Db::rollBack();
            _Error($exception->getMessage());
        }
        return $productObject;
    }

    private function updateAttrResult($productObject, $attrs, $attrData)
    {
        $result = $this->getAttrResult((clone $attrs), $attrData);
        $productObject->StoreProductAttrResult()->updateOrCreate([
            'result' => json_encode($result)
        ]);
    }
//    public function edit($id, $params)
//    {
//        $productObject = $this->productModel->find($id);
//
//        $productObject->fill($params);
//        $productObject->productDownload()->update(array_intersect_key($params, ['url']));
//        $productObject->productContent()->update(array_intersect_key($params, ['conent']));
//        return $productObject->save();
//    }

    public function detail($productId)
    {
        return $this->storeProductDao->with(['StoreProductAttr', 'StoreProductDescription', 'StoreProductAttrValue', 'StoreProductAttrResult'])->where('id', $productId)->first();
    }

    public function lists($params)
    {
        $data = $this->storeProductDao->lists($params);
        return $data;
    }

    public function getHeader()
    {
        //出售中的商品
        $onsale = $this->storeProductDao->getCount(_Collect(['type' => 1]));

        $forsale = $this->storeProductDao->getCount(_Collect(['type' => 2]));
        //已经售馨商品
        $outofstock = $this->storeProductDao->getCount(_Collect(['type' => 4]));
        //警戒库存商品
        $policeforce = $this->storeProductDao->getCount(_Collect(['type' => 5, 'store_stock' => 2]));

        //回收站的商品
        $recycle = $this->storeProductDao->getCount(_Collect(['type' => 6]));
        return [
            ['type' => 1, 'name' => '出售中的商品', 'count' => $onsale],
            ['type' => 2, 'name' => '仓库中的商品', 'count' => $forsale],
            ['type' => 4, 'name' => '已经售馨商品', 'count' => $outofstock],
            ['type' => 5, 'name' => '警戒库存商品', 'count' => $policeforce],
            ['type' => 6, 'name' => '回收站的商品', 'count' => $recycle]
        ];
    }

    private function getAttrResult(Collect $attr, Collect $value)
    {
        $attr->transform(function ($item) use (&$detail) {
            return [
                'value' => $item['title'],
                'detail' => json_decode($item['values'], true),
            ];
        });

        $value->transform(function ($item, $key) use ($attr) {
            $detail = [];
            $result = [];
            foreach ($item['attr'] as $k => $v) {
                $detail[$attr[$k]['value']] = $v;
                $result['value' . ($k + 1)] = $v;
            }
            $result['suk'] = implode(',', $item['attr']);
            $result['detail'] = $detail;
            return $result + Arr::only($item, ['id', 'price', 'pic', 'cost', 'ot_price', 'vip_price', 'stock', 'bar_code', 'weight', 'volume']);
        });
        return [
            'attr' => $attr->all(),
            'value' => $value->all(),
        ];
    }

    private function updateAttrValue(\Hyperf\DbConnection\Model\Model $productObject, Collect $attrData)
    {

        $deleteIds = $attrData->pluck('id');
        $productObject->StoreProductAttrValue()->whereNotIn('id', $deleteIds->all())->delete();

        $addAttrData = $attrData->where('id', 0);
        $addAttrData->transform(function ($attr) {
            return new StoreProductAttrValue($attr);
        });
        $productObject->StoreProductAttrValue()->saveMany($addAttrData);

        $updateAttrData = $attrData->where('id', '>', 0);

        $updateAttrData->every(function ($attr) use ($productObject) {
            $StoreProductAttrData = $productObject->StoreProductAttrValue()->where('id', $attr['id'])->firstOrError();
            $StoreProductAttrData->fill($attr);
            return $StoreProductAttrData->save();
        });

    }

    private function updateAttr(StoreProduct $productObject, Collect $attrs)
    {

        $deleteIds = $attrs->pluck('id');
        $productObject->StoreProductAttr()->whereNotIn('id', $deleteIds->all())->delete();

        $attrs->transform(function ($attr) {
            return [
                'id' => $attr['id'],
                'attr_name' => $attr['title'],
                'attr_values' => implode(', ', json_decode($attr['values'], true)),
            ];
        });

        $addAttr = $attrs->where('id', 0);
        $addAttr->transform(function ($attr) {
            return new StoreProductAttr($attr);
        });
        $productObject->StoreProductAttr()->saveMany($addAttr);

        $updateAttr = $attrs->where('id', '>', 0);
        $updateAttr->every(function ($attr) use ($productObject) {
            $StoreProductAttrData = $productObject->StoreProductAttr()->where('id', $attr['id'])->firstOrError();
            $StoreProductAttrData->fill($attr);
            return $StoreProductAttrData->save();
        });


    }

}